package com.yupi.springbootinit.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.springbootinit.annotation.AuthCheck;
import com.yupi.springbootinit.common.BaseResponse;
import com.yupi.springbootinit.common.DeleteRequest;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.common.ResultUtils;
import com.yupi.springbootinit.constant.UserConstant;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.exception.ThrowUtils;
import com.yupi.springbootinit.mapper.PostMapper;
import com.yupi.springbootinit.model.dto.post.PostEditRequest;
import com.yupi.springbootinit.model.dto.post.PostQueryRequest;
import com.yupi.springbootinit.model.dto.post.PostUpdateRequest;
import com.yupi.springbootinit.model.entity.Post;
import com.yupi.springbootinit.model.entity.User;
import com.yupi.springbootinit.model.vo.PostVO;
import com.yupi.springbootinit.service.PostService;
import com.yupi.springbootinit.service.UserService;

import java.time.LocalDateTime;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/post")
@Slf4j
public class PostController {

    @Resource
    private PostService postService;

    @Resource
    private UserService userService;

    @Resource
    private PostMapper postMapper;

    // region 增删改查

    @GetMapping("/postById")
    public PostVO getPostById(@RequestParam Long postid) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("postId", postid);
        PostVO post = PostVO.objToVo(postMapper.selectOne(queryWrapper));
        return post;
    }

    @GetMapping("/page")
    public Page<Post> getPostsByPage(@RequestParam int current, @RequestParam int size, @RequestParam(required = false, defaultValue = "") String tag) {
        ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
        Page<Post> page = new Page<>(current, size);

        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();

        if (!tag.equals("")) {
            queryWrapper.eq("tags", "[\"" + tag + "\"]");
        }

        queryWrapper.orderByDesc("createTime");
        queryWrapper.like("isDelete", 0);
        queryWrapper.eq("isTop", 0);
        // 调用Mapper的selectPage方法进行分页查询
        // 假设你的Mapper接口有一个selectPage方法，它接受一个IPage对象作为参数
        postMapper.selectPage(page, queryWrapper); // 第二个参数是查询条件，这里为null表示没有条件，你可以根据需要构建QueryWrapper或LambdaQueryWrapper

        // selectPage方法会填充page对象，包括数据列表和分页信息
        // 直接返回这个page对象即可，Spring会将其自动转换为JSON格式
        return page;
    }

    /**
     * 获取置顶帖
     * @param tag
     * @return
     */
    @GetMapping("getIsTopPost")
    public BaseResponse<List<Post>> getIsTopPost(@RequestParam(required = false, defaultValue = "") String tag) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();

        if (!tag.equals("")) {
            queryWrapper.eq("tags", "[\"" + tag + "\"]");
        }

        queryWrapper.orderByDesc("createTime");
        queryWrapper.eq("isDelete", 0);
        queryWrapper.eq("isTop", 1);
        List<Post> posts = postMapper.selectList(queryWrapper);
        return ResultUtils.success(posts);
    }

    /**
     * 文章置顶（管理员）
     * @param postid
     * @return
     */

    @GetMapping("addIsTopPost")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<String> addIsTopPost(@RequestParam Long postid) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", postid);
        queryWrapper.eq("isTop", 0);
        queryWrapper.eq("isDelete", 0);
        Post post = postMapper.selectOne(queryWrapper);
        if (post == null) {
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "该文章不存在或已被置顶");
        }
        post.setIsTop(1);
        postMapper.updateById(post);
        return ResultUtils.success("置顶成功");
    }

    /**
     * 文章取消置顶（管理员）
     */
    @GetMapping("cancelIsTopPost")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<String> cancelIsTopPost(@RequestParam Long postid) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", postid);
        queryWrapper.eq("isDelete", 0);
        queryWrapper.eq("isTop", 1);
        Post post = postMapper.selectOne(queryWrapper);
        if (post == null) {
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "该文章不存在或已被取消置顶");
        }
        post.setIsTop(0);
        postMapper.updateById(post);
        return ResultUtils.success("取消成功");
    }




    /**
     * 创建
     *
     * @param request
     * @return
     */
    @PostMapping("/add")
    public BaseResponse<Long> addPost(@RequestParam(value = "title") String title,
                                      @RequestParam(value = "content") String content,
                                      @RequestParam(value = "tags") List<String> tags,
                                      @RequestParam(value = "anon", defaultValue = "0") Integer anon,
                                      @RequestParam(value = "files", required = false) List<MultipartFile> files, HttpServletRequest request) {
        Post post = new Post();
        post.setTitle(title);
        post.setContent(content);
        post.setAnon(anon);
        if (tags != null) {
            post.setTags(JSONUtil.toJsonStr(tags));
        }
        postService.validPost(post, true);
        User loginUser = userService.getLoginUser(request);

        if (loginUser.getIsAuth() == 0) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "请先实名认证再发帖哦~");
        }
        if (loginUser.getUserPoints() <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "积分不足");
        }
        post.setUserId(loginUser.getId());
        if (post.getAnon() == 1) {
            post.setAnon_name(loginUser.getAnon_name());
        }
        post.setFavourNum(0);
        post.setThumbNum(0);
        if (files != null) {
            List<String> imgpath = postService.uploadImage(files);

            post.setImgpath(JSONUtil.toJsonStr(imgpath));
        }

        boolean result = postService.save(post);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        boolean reduceOnePoint = userService.reduceOnePoint(loginUser);
        ThrowUtils.throwIf(!reduceOnePoint, ErrorCode.SYSTEM_ERROR);
        long newPostId = post.getId();
        return ResultUtils.success(newPostId);
    }

    /**
     * 删除
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> deletePost(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userService.getLoginUser(request);
        long id = deleteRequest.getId();
        // 判断是否存在
        Post oldPost = postService.getById(id);
        ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR);
        // 仅本人或管理员可删除
        if (!oldPost.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        boolean b = postService.removeById(id);
        return ResultUtils.success(b);
    }

    /**
     * 更新（仅管理员）
     *
     * @param postUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> updatePost(@RequestBody PostUpdateRequest postUpdateRequest) {
        if (postUpdateRequest == null || postUpdateRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Post post = new Post();
        BeanUtils.copyProperties(postUpdateRequest, post);
        List<String> tags = postUpdateRequest.getTags();
        if (tags != null) {
            post.setTags(JSONUtil.toJsonStr(tags));
        }
        // 参数校验
        postService.validPost(post, false);
        long id = postUpdateRequest.getId();
        // 判断是否存在
        Post oldPost = postService.getById(id);
        ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR);
        boolean result = postService.updateById(post);
        return ResultUtils.success(result);
    }

    /**
     * 根据 id 获取
     *
     * @param id
     * @return
     */
    @GetMapping("/get/vo")
    public BaseResponse<PostVO> getPostVOById(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Post post = postService.getById(id);
        if (post == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return ResultUtils.success(postService.getPostVO(post, request));
    }



//    /**
//     * 编辑（用户）
//     *
//     * @param postEditRequest
//     * @param request
//     * @return
//     */
//    @PostMapping("/edit")
//    public BaseResponse<Boolean> editPost(@RequestBody PostEditRequest postEditRequest, HttpServletRequest request) {
//        if (postEditRequest == null || postEditRequest.getId() <= 0) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR);
//        }
//        Post post = new Post();
//        BeanUtils.copyProperties(postEditRequest, post);
//        List<String> tags = postEditRequest.getTags();
//        if (tags != null) {
//            post.setTags(JSONUtil.toJsonStr(tags));
//        }
//        // 参数校验
//        postService.validPost(post, false);
//        User loginUser = userService.getLoginUser(request);
//        long id = postEditRequest.getId();
//        // 判断是否存在
//        Post oldPost = postService.getById(id);
//        ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR);
//        // 仅本人或管理员可编辑
//        if (!oldPost.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
//            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
//        }
//        boolean result = postService.updateById(post);
//        return ResultUtils.success(result);
//    }

    @GetMapping("/seeNumUp")
    public BaseResponse<Integer> increasePostViewCount(@RequestParam long postid) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("id", postid);
        Post post = postMapper.selectOne(queryWrapper);
        if (post == null) {
            // 处理找不到帖子的情况，可以返回错误或适当的默认值
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }
        int newSeeNum = post.getSeeNum() + 3;
        post.setSeeNum(newSeeNum);
        // 假设postService.update方法内部已经妥善处理了事务
        boolean updateSuccess = postService.updateById(post);
        if (!updateSuccess) {
            // 处理更新失败的情况
            return ResultUtils.error(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success(newSeeNum);
    }

    /**
     * 点赞帖子
     * @param postid
     * @return
     */

    @GetMapping("/favourPost")
    public BaseResponse<Integer> favourPost(@RequestParam long postid) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("id", postid);
        Post post = postMapper.selectOne(queryWrapper);
        if (post == null) {
            // 处理找不到帖子的情况，可以返回错误或适当的默认值
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }
        int newFavourNum = post.getFavourNum() + 1;
        post.setFavourNum(newFavourNum);
        // 假设postService.update方法内部已经妥善处理了事务
        boolean updateSuccess = postService.updateById(post);
        if (!updateSuccess) {
            // 处理更新失败的情况
            return ResultUtils.error(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success(newFavourNum);
    }

    @GetMapping("/getPostsByUserId")
    public BaseResponse<List<Post>> getPostsByUserId(HttpServletRequest request) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        User user = userService.getLoginUser(request);
        Long userId = user.getId();
        queryWrapper.eq("userId", userId);
        queryWrapper.eq("isDelete", 0);
        queryWrapper.orderByDesc("createTime");
        List<Post> posts = postMapper.selectList(queryWrapper);
        return ResultUtils.success(posts);
    }

    @GetMapping("/getTopTenPosts")
    public BaseResponse<List<Post>> getTopTenPosts() {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("isDelete", 0);
        queryWrapper.orderByDesc("seeNum");
//        queryWrapper.gt("seeNum", 100);
        queryWrapper.last("limit 10");
        LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);
        LocalDateTime now = LocalDateTime.now();
        queryWrapper.ge("createTime", sevenDaysAgo).lt("createTime", now);
        List<Post> posts = postMapper.selectList(queryWrapper);
        return ResultUtils.success(posts);
    }


//    @PostMapping("/uppostimg")
//    public BaseResponse<List<String>> uppostimg(@RequestParam("files") List<MultipartFile> files) {
//        return ResultUtils.success(postService.uploadImage(files));
//    }

    /**
     * 删除前3个月之前的贴子
     */
    @GetMapping("/deleteOldPost")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<String> deleteOldPost() {
        boolean deleteOldPost = postService.deleteOldPost();
        return ResultUtils.success(deleteOldPost ? "删除成功" : "删除失败");
    }


    /**
     * 分页搜索（从 ES 查询，封装类）
     *
     * @param postQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/search/page/vo")
    public BaseResponse<Page<Post>> searchPostVOByPage(@RequestBody PostQueryRequest postQueryRequest,
                                                         HttpServletRequest request) {
        long size = postQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
        Page<Post> postPage = postService.searchFromEs(postQueryRequest);
        return ResultUtils.success(postPage);
    }



}
